#pragma once
/// Copyright 2012, Alex Averian, Yonan Research
/// Released under BSD Licence

#include "qwindow.h"
#include "qarray.h"

using namespace micro::gui;
using namespace micro::utils;

namespace micro
{
namespace dialog
{



class QDialogBase: public QWindow
{
protected:
    QWindow* 	m_parent;
    UINT		m_id;
    
public:


    QDialogBase( QWindow* p = nullptr ): m_parent( p )
    {
        m_id = 0;
    }
    virtual ~QDialogBase( void ) {   };
    
    
    INT_PTR CreateModal( LPCTSTR templateName );
    INT_PTR CreateModal( UINT resID ) ;
    
    void	SetParent( QWindow* p )
    {
        m_parent = p;
    }
    void	CenterWindow( );

	//inter thread close and destroy
    void Close()
    {
        SendMessage( WM_CLOSE );
    }

protected:
    static INT_PTR APIENTRY DialogProcedure( HWND hwnd, UINT message,  WPARAM wParam, LPARAM lParam );
    
    
protected:
    virtual bool OnInit()
    {
        //CenterWindow();
        return UpdateDialog();
    }
    virtual bool UpdateDialog( bool dir = true )
    {
        return true;
    }
    virtual bool OnButtonClicked( int buttonID, HWND buttonHWND );
    
    
    virtual bool OnMessage( UINT message, WPARAM wParam, LPARAM lParam );
    
    virtual bool OnCommand( WPARAM wParam, LPARAM lParam );
    //virtual bool OnCommand(int code, int itemID, LPARAM lParam);
    virtual bool OnHelp( LPHELPINFO helpInfo )
    {
        return OnHelp();
    }
    virtual bool OnHelp()
    {
        return true;
    }
    virtual bool OnClose()
    {
        return false;
    }
    
    virtual bool OnOK() = 0;
    virtual bool OnCancel() = 0;
    virtual bool OnNotify( UINT_PTR controlID, LPNMHDR lParam, LRESULT& lResult )
    {
        return false;
    }
    virtual bool OnTimer( UINT_PTR id  )
    {
        return false;
    }
    
    
    
    
public:

    HWND	GetItem( int itemID ) const
    {
        return ::GetDlgItem( _window, itemID );
    }
    
    bool	EnableItem( int itemID, bool enable ) const
    {
        return toBool(  ::EnableWindow(  GetItem( itemID ) , toBOOL( enable )  ) );
    }
    
    bool	SetItemText( int itemID, LPCTSTR s )
    {
        return toBool( SetDlgItemText( _window, itemID, s ) );
    }
    
    
    
    UINT	GetItemText( int itemID, LPTSTR string, int maxCount )
    {
        return GetDlgItemText( _window, itemID, string, maxCount );
    }
    
    
    bool	SetItemInt( int itemID, UINT value, bool isSigned )
    {
        return toBool( SetDlgItemInt( _window, itemID, value, toBOOL( isSigned ) ) );
    }
    
    
    bool GetItemInt( int itemID, bool isSigned, UINT& value )
    {
        BOOL result;
        value = GetDlgItemInt( _window, itemID, &result, toBOOL( isSigned ) );
        return toBool( result );
    }
    
    
    
    HWND GetNextGroupItem( HWND control, bool previous )
    {
        return GetNextDlgGroupItem( _window, control, toBOOL( previous ) );
    }
    HWND GetNextTabItem( HWND control, bool previous )
    {
        return GetNextDlgTabItem( _window, control, toBOOL( previous ) );
    }
    
    bool MapRect( LPRECT rect )
    {
        return toBool( MapDialogRect( _window, rect ) );
    }
    
    bool IsMessage( LPMSG message )
    {
        return toBool( IsDialogMessage( _window, message ) );
    }
    
    LRESULT SendItemMessage( int itemID, UINT message, WPARAM wParam, LPARAM lParam )
    {
        return SendDlgItemMessage( _window, itemID, message, wParam, lParam );
    }
    
    bool CheckButton( int buttonID, UINT checkState )
    {
        return toBool( CheckDlgButton( _window, buttonID, checkState ) );
    }
    bool CheckButton( int buttonID, bool checkState )
    {
        return CheckButton( buttonID, UINT( checkState ? BST_CHECKED : BST_UNCHECKED ) );
    }
    
    UINT IsButtonChecked( int buttonID ) const
    {
        return IsDlgButtonChecked( _window, buttonID );
    }
    bool IsButtonCheckedBool( int buttonID ) const
    {
        return ( IsButtonChecked( buttonID ) == BST_CHECKED );
    }
    
    bool CheckRadioButton( int firstButtonID, int lastButtonID, int checkButtonID )
    {
        return toBool( ::CheckRadioButton( _window, firstButtonID, lastButtonID, checkButtonID ) );
    }
    
    
    
    LONG_PTR SetMsgResult( LONG_PTR newLongPtr )
    {
        return SetWindowLong( DWLP_MSGRESULT, newLongPtr );
    }
    LONG_PTR GetMsgResult() const
    {
        return GetWindowLong( DWLP_MSGRESULT );
    }
};








class QDialog: public QDialogBase
{

public:
    QDialog( QWindow* parent = nullptr ): QDialogBase( parent ) {  };
    virtual ~QDialog() { };
    
    bool End( INT_PTR result )
    {
        return toBool( ::EndDialog( _window, result ) );
    }
    
protected:
    virtual bool OnInit()
    {
        CenterWindow();
        return  QDialogBase::OnInit();//calls UpdateDialog
    }
    
    //dir = direction
    //true: class -> dialog
    //false: dialog->class
    virtual bool UpdateDialog( bool dir = true )
    {
        return true;
    }
    
    
    virtual bool OnOK()
    {
        if ( UpdateDialog( false ) )
            return End( IDOK );
            
        return false;
    }
    virtual bool OnCancel()
    {
        return End( IDCANCEL );
    }
    virtual bool OnClose()
    {
        return  End( IDCANCEL );
    }
    
public:
    virtual INT_PTR DoModal()
    {
        return CreateModal( m_id );
    }
    
    
};



class QModelessDialog: public QDialogBase
{
public:
    QModelessDialog( QWindow* p ): QDialogBase( p )
    {
    };
    
    virtual ~QModelessDialog()
    {
        //nu e bun pt interthread
        //e necesar in mod uzual
        ///Destroy();
        
    } //nu se poate apela din alt fir
    
    bool CreateModelessDialog();	//create but do not show
    
    virtual bool OnInit()
    {
        //CenterWindow();
        return QDialogBase::OnInit();//calls UpdateDialog();
    }
    
    virtual bool UpdateDialog( bool dir = true )
    {
        return true;
    }
    
    virtual bool OnOK()
    {
        if ( UpdateDialog( false ) )
            Destroy();
            
        return true;
    }
    virtual bool OnCancel()
    {
        Destroy();
        return true;
    }
    virtual bool OnClose()
    {
        Destroy();
        return true;
    }
    
    virtual bool DoModeless();
    
};





////////////////////////////////// RESIZEDIALOGS //////////////////////////////////////////////////////////


//DEFINE_ENUM_FLAG_OPERATORS(ANCHOR_FLAGS);


class QResizeDialog: public QDialog
{
    typedef enum ANCHOR_FLAGS
    {
        AF_LEFT             = 0x01,
        AF_RIGHT            = 0x02,
        AF_LEFT_AND_RIGHT   = 0x03,
        AF_TOP              = 0x04,
        AF_BOTTOM           = 0x08,
        AF_TOP_AND_BOTTOM   = 0x0C,
    } ANCHOR_FLAGS;
    struct ANCHOR
    {
        UINT			idControl;
        UINT			aff;
        RECT			rect;
    };
    QArray<ANCHOR>		m_anchors;
    
    
public:
    QResizeDialog( QWindow* parent = nullptr ): QDialog( parent ) {  };
    virtual ~QResizeDialog() { };
    
    
protected:
    virtual bool OnInit()
    {
        OnInitResize();
        return QDialog::OnInit();
    }
    virtual bool OnSize()
    {
        return true;
    }
    virtual bool OnInitResize()
    {
        /* initialize m_ancors in derived class*/ return true;
    }
    
    
protected:
    void	GetWindowRectInClient( UINT id,		RECT* prect );
    void	GetWindowRectInClient( HWND hwnd,	RECT* prect );
    
    void	InitResizeData();
    void	ReSizeControls();
    
};





}
}//micro